package com.zoffy.zoffyapi.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.zoffy.zoffyapi.exception.BusinessException;
import com.zoffy.zoffyapi.exception.ErrorCode;
import com.zoffy.zoffyapi.model.dto.user.UserInfoUpdateRequest;

import com.zoffy.zoffyapi.model.vo.AkSkRequest;
import com.zoffy.zoffyapi.model.vo.AkSkVo;
import com.zoffy.zoffyapi.model.vo.UserVo;
import com.zoffy.zoffyapi.service.UserService;
import com.zoffy.zoffyapi.mapper.UserMapper;

import com.zoffy.zoffyapicommon.model.entity.User;
import jakarta.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* @author zoffy
* description 针对表【user(用户)】的数据库操作Service实现
* createDate 2023-12-05 19:04:18
*/
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
    implements UserService{

    @Override
    public long userRegister(String userAccount, String userPassword, String checkPassword) {
        //非空校验
        if(StringUtils.isAnyEmpty(userAccount,userPassword,checkPassword)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"请求参数为空");
        }
        //密码和确认密码必须相同
        if (!userPassword.equals(checkPassword)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"两次密码不相同");
        }
        //账号长度不低于4，密码长度不低于8
        if (userAccount.length()<4||userPassword.length()<8) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"账号密码长度非法");
        }
        //特殊字符校验
        String regx="[\\\\u\\\"`~!@#$%^&*()+=|{}':;',\\\\[\\\\].<>/?~！@#￥%……&*（）——+|{}【】‘；：”“'。，、？]";
        Matcher matcher= Pattern.compile(regx).matcher(userAccount);
        if( matcher.find()){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"用户名含敏感字符");
        }
        //账号不能重复
        QueryWrapper<User> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("user_account",userAccount);
        long count=this.count(queryWrapper);
        if(count>0){
            throw new BusinessException(ErrorCode.FORBIDDEN_ERROR,"用户名重复");
        }
        //密码加密
        String encryptPassword=md5Hex(userPassword);
        //创建用户
        User user=new User();
        user.setUserAccount(userAccount);
        user.setUserPassword(encryptPassword);

        user.setAccessKey(genKey(userAccount));
        user.setSecretKey(genKey(userAccount));
        boolean saveResult = this.save(user);
        if (!saveResult){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"用户已存在");
        }
        return user.getId();
    }

    @Override
    public UserVo userLogin(HttpServletRequest request, String userAccount, String userPassword) {
        //非空校验
        if(StringUtils.isAnyEmpty(userAccount,userPassword)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"用户密码不能为空");
        }
        //长度校验
        if (userAccount.length()<4||userPassword.length()<8) {
            throw new BusinessException(ErrorCode.FORBIDDEN_ERROR,"账号或密码错误");
        }
        //密码加密
        String encryptPassword=md5Hex(userPassword);
        //登录校验
        QueryWrapper<User> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("user_account",userAccount);
        queryWrapper.eq("user_password",encryptPassword);
        User user=this.getOne(queryWrapper);
        if(user==null){
            throw new BusinessException(ErrorCode.FORBIDDEN_ERROR,"账号或密码错误");
        }
        //数据脱敏
        UserVo userVo=getUserVo(user);
        //保存登录态
        request.getSession().setAttribute("loginState",userVo);
        return userVo;
    }

    @Override
    public UserVo getCurrentUserVo(HttpServletRequest request) {
        UserVo loginUserVo=(UserVo) request.getSession().getAttribute("loginState");
        if(loginUserVo==null){
            throw new BusinessException(ErrorCode.FORBIDDEN_ERROR,"用户未登录");
        }

        return getUserVo(this.getById(loginUserVo.getId()));
    }

    @Override
    public User getCurrentUser(HttpServletRequest request) {
        UserVo loginUserVo=(UserVo) request.getSession().getAttribute("loginState");
        if(loginUserVo==null){
            throw new BusinessException(ErrorCode.FORBIDDEN_ERROR,"用户未登录");
        }

        return this.getById(loginUserVo.getId());
    }

    @Override
    public UserVo updateUserInfo(HttpServletRequest request, UserInfoUpdateRequest userInfoUpdateRequest) {
        String userName = userInfoUpdateRequest.getUserName();
        int gender = userInfoUpdateRequest.getGender();
        if (StringUtils.isBlank(userName)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        if (gender!=0 && gender!=1){
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        UserVo userVo = getCurrentUserVo(request);
        User user=new User();
        user.setId(userVo.getId());
        user.setUserName(userName);
        user.setGender(gender);
        this.updateById(user);
        userVo.setUserName(userName);
        userVo.setGender(gender);
        return userVo;
    }

    @Override
    public AkSkVo getAkSk(HttpServletRequest request, AkSkRequest akSkRequest) {
        String userPassword = akSkRequest.getUserPassword();
        User user = checkPassword(request, userPassword);
        AkSkVo akSkVo=new AkSkVo();
        akSkVo.setAccessKey(user.getAccessKey());
        akSkVo.setSecretKey(user.getSecretKey());
        return akSkVo;

    }

    @Override
    public AkSkVo updateAkSk(HttpServletRequest request, AkSkRequest akSkRequest) {
        String userPassword = akSkRequest.getUserPassword();
        User oldUser = checkPassword(request, userPassword);
        String userAccount=oldUser.getUserAccount();
        User user=new User();
        user.setId(oldUser.getId());

        user.setAccessKey(genKey(userAccount));
        user.setSecretKey(genKey(userAccount));
        this.updateById(user);
        AkSkVo akSkVo=new AkSkVo();
        akSkVo.setAccessKey(user.getAccessKey());
        akSkVo.setSecretKey(user.getSecretKey());
        return akSkVo;
    }

    /**
     * md5加密
     * @param origin 原始字符串
     * @return 加密后的字符串
     */
    private String md5Hex(String origin){
        final String SALT="zoffy";
        return DigestUtils.md5DigestAsHex((SALT+origin).getBytes());
    }

    /**
     * 用户信息脱敏
     * @param user 原始用户实体信息
     * @return 脱敏后的实体信息
     */
    private UserVo getUserVo(User user){
        UserVo userVo=new UserVo();
        userVo.setId(user.getId());
        userVo.setUserName(user.getUserName());
        userVo.setUserAccount(user.getUserAccount());
        userVo.setUserAvatar(user.getUserAvatar());
        userVo.setGender(user.getGender());
        userVo.setUserRole(user.getUserRole());
        userVo.setCreateTime(user.getCreateTime());
        return userVo;
    }

    /**
     * 使用md5生成随机密钥
     * @param userAccount 加盐字符串，推荐使用用户账号
     * @return 生成的密钥
     */
    public String genKey(String userAccount){
        return md5Hex(userAccount+RandomStringUtils.random(6));
    }

    /**
     * 检查用户密码是否正确，正确则返回User对象，否则抛出异常
     * @param request HttpServletRequest
     * @param userPassword 用户密码
     * @return User
     */
    private User checkPassword(HttpServletRequest request,String userPassword){
        if(userPassword==null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        UserVo currentUser = getCurrentUserVo(request);
        long id = currentUser.getId();
        QueryWrapper<User> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("id",id);
        queryWrapper.eq("user_password",md5Hex(userPassword));
        User oldUser = this.getOne(queryWrapper);
        if (oldUser==null){
            throw new BusinessException(ErrorCode.FORBIDDEN_ERROR,"密码错误");
        }
        return oldUser;
    }
}




